home *** CD-ROM | disk | FTP | other *** search
- /*
- File: KeyboardModule.c
-
- Contains: HID Module for USB Keyboard
-
- Version: xxx put version here xxx
-
- Copyright: © 1997-1998 by Apple Computer, Inc., all rights reserved.
-
- */
-
- #include <Types.h>
- #include <Devices.h>
- #include <processes.h>
- #include <DriverServices.h>
- #include <USB.h>
-
- #include "KeyboardModule.h"
-
- usbKeyboardPBStruct myKeyboardPB;
- usbKeyboardPBStruct shimKeyboardPB;
-
-
- static void KeyboardModuleDelay1CompletionProc(USBPB *pb);
- void SetParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock);
-
- void SetParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock)
- {
- paramblock->usbReference = theDeviceRef;
- paramblock->pbVersion = kUSBCurrentPBVersion;
- paramblock->usbWIndex = 0;
- paramblock->usbBuffer = nil;
- paramblock->usbStatus = noErr;
- paramblock->usbReqCount = 0;
- paramblock->usbWValue = 0;
- paramblock->usbFlags = 0;
- }
-
- static Boolean immediateError(OSStatus err)
- {
- return((err != kUSBPending) && (err != noErr) );
- }
-
- void KeyboardModuleInitiateTransaction(USBPB *pb)
- {
- register usbKeyboardPBStruct *pKeyboardPB;
- OSStatus myErr;
-
- pKeyboardPB = (usbKeyboardPBStruct *)(pb);
- pKeyboardPB->transDepth++;
- if (pKeyboardPB->transDepth < 0)
- {
- USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: transDepth < 0 (initiation)", pKeyboardPB->pb.usbRefcon );
- }
-
- if (pKeyboardPB->transDepth > 1)
- {
- USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: transDepth > 1 (initiation)", pKeyboardPB->pb.usbRefcon );
- }
-
- switch(pKeyboardPB->pb.usbRefcon & ~kRetryTransaction)
- {
- case kSetKeyboardLEDs:
- SetParamBlock(pKeyboardPB->deviceRef, &pKeyboardPB->pb);
-
- pKeyboardPB->pb.usbBMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);
-
- pKeyboardPB->pb.usbBRequest = kHIDRqSetReport;
- pKeyboardPB->pb.usbWValue = (kHIDRtOutputReport << 8);
- pKeyboardPB->pb.usbWIndex = pKeyboardPB->pInterfaceDescriptor->interfaceNumber;
-
- pKeyboardPB->pb.usbBuffer = (Ptr)&pKeyboardPB->hidReport[0];
- pKeyboardPB->pb.usbReqCount = 1;
-
- pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
- pKeyboardPB->pb.usbRefcon |= kCompletionPending;
-
- myErr = USBDeviceRequest(&pKeyboardPB->pb);
- if(immediateError(myErr))
- {
- USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: kSetKeyboardLEDs - immediate error", myErr);
- }
- break;
-
- case kGetFullConfiguration:
- SetParamBlock(pKeyboardPB->deviceRef, &pKeyboardPB->pb);
-
- pKeyboardPB->pb.usbRefcon |= kCompletionPending;
- pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
- myErr = USBGetFullConfigurationDescriptor(pb);
- if(immediateError(myErr))
- {
- USBExpertFatalError(pKeyboardPB->pb.usbReference, kUSBInternalErr, "\pUSBHIDKeyboardModule: kGetFullConfiguration (ImmediateError)", myErr);
- }
- break;
-
- case kFindInterfaceAndSetProtocol:
- myErr = FindHIDInterfaceByNumber(pKeyboardPB->pFullConfigDescriptor, pKeyboardPB->interfaceDescriptor.interfaceNumber, &pKeyboardPB->pInterfaceDescriptor ); // find the HID interface
- if ((pKeyboardPB->pInterfaceDescriptor == NULL) ||
- (myErr != noErr))
- {
- USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: Interface not found", myErr);
- pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
- }
-
- SetParamBlock(pKeyboardPB->deviceRef, &pKeyboardPB->pb);
-
- pKeyboardPB->pb.usbBMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);
- pKeyboardPB->pb.usbBRequest = kHIDRqSetProtocol;
- pKeyboardPB->pb.usbWValue = kHIDBootProtocolValue;
- pKeyboardPB->pb.usbWIndex = pKeyboardPB->pInterfaceDescriptor->interfaceNumber;
- pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
-
- pKeyboardPB->pb.usbRefcon |= kCompletionPending;
- myErr = USBDeviceRequest(&pKeyboardPB->pb);
- if (immediateError(myErr))
- {
- USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: kSetProtocol (ImmediateError)", myErr);
- }
- break;
-
- case kSetIdleRequest:
- SetParamBlock(pKeyboardPB->deviceRef, &pKeyboardPB->pb);
-
- pKeyboardPB->pb.usbBMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);
-
- pKeyboardPB->pb.usbBRequest = kHIDRqSetIdle;
- pKeyboardPB->pb.usbWValue = ((24/4)<<8); // force a read completion if idle for more than 24ms
- pKeyboardPB->pb.usbWIndex = pKeyboardPB->pInterfaceDescriptor->interfaceNumber;
- pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
-
- pKeyboardPB->pb.usbRefcon |= kCompletionPending;
-
- myErr = USBDeviceRequest(&pKeyboardPB->pb);
- if(immediateError(myErr))
- {
- USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: kSetIdleRequest - immediate error", myErr);
- }
- break;
-
- case kFindAndOpenInterruptPipe:
- pKeyboardPB->pb.usbBMRequestType = USBMakeBMRequestType(kUSBIn, kUSBClass, kUSBInterface);
- pKeyboardPB->pb.usbFlags = kUSBIn;
- pKeyboardPB->pb.usbClassType = kUSBInterrupt;
- pKeyboardPB->pb.usbOther = 0;
- pKeyboardPB->pb.usbBuffer = pKeyboardPB->pInterfaceDescriptor;
- pKeyboardPB->pb.usbReqCount = (UInt8*)pKeyboardPB->pInterfaceDescriptor - (UInt8*)pKeyboardPB->pFullConfigDescriptor;
- myErr = USBFindNextEndpointDescriptorImmediate( &pKeyboardPB->pb );
- if((immediateError(myErr)) || (pKeyboardPB->pb.usbBuffer == nil))
- {
- USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: Endpoint not found", myErr);
- pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
- }
- else
- {
- pKeyboardPB->pEndpointDescriptor = (USBEndPointDescriptorPtr) pKeyboardPB->pb.usbBuffer;
-
- SetParamBlock(pKeyboardPB->deviceRef, &pKeyboardPB->pb);
-
- pKeyboardPB->pb.usbFlags = kUSBIn;
- pKeyboardPB->pb.usbWValue = 0x08;
- pKeyboardPB->pb.usbClassType = kUSBInterrupt;
- pKeyboardPB->pb.usbOther = (pKeyboardPB->pEndpointDescriptor->endpointAddress & 0x0f);
- pKeyboardPB->pb.usbRefcon |= kCompletionPending;
- pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
-
- myErr = USBOpenPipe( &pKeyboardPB->pb );
- if(immediateError(myErr))
- {
- USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: USBOpenPipe Failed (ImmediateError)", myErr);
- }
- }
- break;
-
- case kReadInterruptPipe:
- SetParamBlock(pKeyboardPB->pipeRef, &pKeyboardPB->pb);
-
- pKeyboardPB->pb.usbBuffer = (Ptr)pKeyboardPB->hidReport;
- pKeyboardPB->pb.usbReqCount = 0x08;
- pKeyboardPB->pb.usbWIndex = pKeyboardPB->pInterfaceDescriptor->interfaceNumber;
- pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
-
- pKeyboardPB->pb.usbRefcon |= kCompletionPending;
-
- myErr = USBIntRead(&pKeyboardPB->pb);
- if(immediateError(myErr))
- {
- USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: Read Interrupt Pipe (ImmediateError)", myErr);
- }
- break;
-
- default:
- USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule - Transaction completed with bad refcon value", pKeyboardPB->pb.usbRefcon );
- pKeyboardPB->pb.usbRefcon = kUndefined + kReturnFromDriver;
- break;
- }
-
- // At this point the control is returned to the system. If a USB transaction
- // has been initiated, then it will call the Complete procs
- // (below) to handle the results of the transaction.
- }
-
- void KeyboardCompletionProc(USBPB *pb)
- {
- unsigned char * errstring;
- register usbKeyboardPBStruct *pKeyboardPB;
- USBPipeState pipeState;
-
- pKeyboardPB = (usbKeyboardPBStruct *)(pb);
- pKeyboardPB->transDepth--;
- if (pKeyboardPB->transDepth < 0)
- {
- USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: transDepth < 0 (completion)", pKeyboardPB->pb.usbRefcon );
- }
-
- if (pKeyboardPB->transDepth > 1)
- {
- USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule: transDepth > 1 (completion)", pKeyboardPB->pb.usbRefcon );
- }
-
- if(pKeyboardPB->pb.usbStatus != noErr) // was there an error?
- {
- switch(pKeyboardPB->pb.usbRefcon & 0x0fff) // yes, so show where the error occurred
- {
- case kGetFullConfiguration: errstring = "\pUSBHIDKeyboardModule: Error during GetFullConfiguration"; break;
- case kFindInterfaceAndSetProtocol: errstring = "\pUSBHIDKeyboardModule: Error during FindInterfaceAndSetProtocol"; break;
- case kFindAndOpenInterruptPipe: errstring = "\pUSBHIDKeyboardModule: Error during FindAndOpenInterruptPipe"; break;
- case kReadInterruptPipe: errstring = "\pUSBHIDKeyboardModule: Error during ReadInterruptPipe"; break;
- default: errstring = "\pUSBHIDKeyboardModule: Error occurred, but state is unknown"; break;
- };
- USBExpertFatalError(pKeyboardPB->deviceRef, pKeyboardPB->pb.usbStatus, errstring, (pKeyboardPB->pb.usbRefcon & 0x0fff));
-
- pKeyboardPB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver); // set up to retry the transaction
- pKeyboardPB->pb.usbRefcon |= kRetryTransaction;
- pKeyboardPB->retryCount--;
-
- if ((!pKeyboardPB->retryCount) || (pKeyboardPB->pb.usbStatus == kUSBAbortedError)) // have we exhausted the retries?
- { // or received an abort?
- USBExpertStatus(pKeyboardPB->deviceRef, "\pUSBHIDKeyboardModule: Pipe abort or unable to recover from error", pKeyboardPB->deviceRef);
- pKeyboardPB->pb.usbRefcon = kReturnFromDriver; // if so, just exit.
- }
- else // if it didn't abort and there's retries left, then...
- {
- if (pKeyboardPB->pipeRef) // check if the pipe is open.
- {
- USBGetPipeStatusByReference(pKeyboardPB->pipeRef, &pipeState); // yes, so what it's state?
- if (pipeState != kUSBActive) // if it's not active, try to clear it. It might be stalled...
- {
- USBExpertStatus(pKeyboardPB->deviceRef, "\pUSBHIDKeyboardModule: Pipe is open and stalled, clearing stall...", pKeyboardPB->deviceRef);
- USBClearPipeStallByReference(pKeyboardPB->pipeRef);
- }
- }
- }
- }
- else
- {
- pKeyboardPB->pb.usbRefcon &= ~kRetryTransaction;
- pKeyboardPB->retryCount = kKeyboardRetryCount;
- }
-
- if (pKeyboardPB->pb.usbRefcon & kCompletionPending)
- {
- pKeyboardPB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
- switch(pKeyboardPB->pb.usbRefcon)
- {
- case kSetKeyboardLEDs:
- pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
- break;
-
- case kGetFullConfiguration:
- pKeyboardPB->pFullConfigDescriptor = pKeyboardPB->pb.usbBuffer;
- if (pKeyboardPB->pFullConfigDescriptor == nil)
- {
- USBExpertFatalError(pKeyboardPB->pb.usbReference, kUSBInternalErr, "\pUSBHIDKeyboardModule: USBGetFullConfiguration - pointer is nil", pKeyboardPB->pb.usbRefcon);
- pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
- }
- else
- {
- pKeyboardPB->pb.usbRefcon = kFindInterfaceAndSetProtocol;
- }
- break;
-
- case kFindInterfaceAndSetProtocol:
- pKeyboardPB->pb.usbRefcon = kSetIdleRequest;
- break;
-
- case kSetIdleRequest:
- pKeyboardPB->pb.usbRefcon = kFindAndOpenInterruptPipe;
- break;
-
- case kFindAndOpenInterruptPipe:
- pKeyboardPB->pipeRef = pKeyboardPB->pb.usbReference;
- pKeyboardPB->pb.usbRefcon = kReadInterruptPipe;
- break;
-
- case kReadInterruptPipe:
- NotifyRegisteredHIDUser(pKeyboardPB->hidDeviceType, pKeyboardPB->hidReport);
- pKeyboardPB->pb.usbRefcon = kReadInterruptPipe;
- break;
-
- default:
- USBExpertFatalError(pKeyboardPB->deviceRef, kUSBInternalErr, "\pUSBHIDKeyboardModule - Transaction completed with bad refcon value", pKeyboardPB->pb.usbRefcon );
- pKeyboardPB->pb.usbRefcon = kUndefined + kReturnFromDriver;
- break;
- }
- }
- if (!(pKeyboardPB->pb.usbRefcon & kReturnFromDriver))
- KeyboardModuleInitiateTransaction(pb);
- }
-
-
- void InterfaceEntry(UInt32 interfacenum, USBInterfaceDescriptorPtr pInterfaceDescriptor, USBDeviceDescriptorPtr pDeviceDescriptor, USBDeviceRef device)
- {
- #pragma unused (interfacenum)
-
- static Boolean beenThereDoneThat = false;
-
- if(beenThereDoneThat)
- {
- USBExpertFatalError(device, kUSBInternalErr, "\pUSBHIDKeyboardModule is not reentrant", 12);
- return;
- }
- beenThereDoneThat = true;
-
- // DebugStr("\pIn Keyboard Module Interface entry routine");
- shimKeyboardPB.deviceDescriptor = *pDeviceDescriptor;
- shimKeyboardPB.interfaceDescriptor = *pInterfaceDescriptor;
- shimKeyboardPB.transDepth = 0;
- shimKeyboardPB.retryCount = kKeyboardRetryCount;
- shimKeyboardPB.pSHIMInterruptRoutine = nil;
- shimKeyboardPB.pSavedInterruptRoutine = nil;
- shimKeyboardPB.deviceRef = device;
- shimKeyboardPB.interfaceRef = 0;
- shimKeyboardPB.pipeRef = 0;
-
- shimKeyboardPB.deviceRef = device;
- shimKeyboardPB.interfaceRef = nil;
- shimKeyboardPB.pipeRef = nil;
-
- SetParamBlock(device, &shimKeyboardPB.pb);
- shimKeyboardPB.pb.pbLength = sizeof(usbKeyboardPBStruct);
- shimKeyboardPB.pb.usbRefcon = 0;
-
- myKeyboardPB.deviceDescriptor = *pDeviceDescriptor;
- myKeyboardPB.interfaceDescriptor = *pInterfaceDescriptor;
- myKeyboardPB.transDepth = 0;
- myKeyboardPB.retryCount = kKeyboardRetryCount;
- myKeyboardPB.pSHIMInterruptRoutine = nil;
- myKeyboardPB.pSavedInterruptRoutine = nil;
- myKeyboardPB.deviceRef = device;
- myKeyboardPB.interfaceRef = 0;
- myKeyboardPB.pipeRef = 0;
-
- myKeyboardPB.deviceRef = device;
- myKeyboardPB.interfaceRef = nil;
- myKeyboardPB.pipeRef = nil;
-
- myKeyboardPB.sendRawReportFlag = false;
- myKeyboardPB.hidEmulationInit = false;
-
- SetParamBlock(device, &myKeyboardPB.pb);
- myKeyboardPB.pb.pbLength = sizeof(usbKeyboardPBStruct);
- myKeyboardPB.pb.usbRefcon = kGetFullConfiguration; /* Start with setting the interface protocol */
-
-
- USBHIDControlDevice(kHIDEnableDemoMode,0);
- KeyboardModuleInitiateTransaction(&myKeyboardPB.pb);
- }
-
-
-
-